/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package zombiedefense.ui;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionListener;
import javax.swing.JPanel;
import java.awt.Font;
import javax.swing.JLabel;
import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.SpringLayout;
import zombiedefense.framework.ZombieManager;
import zombiedefense.sprites.Gun;
import zombiedefense.sprites.Player;
import static zombiedefense.util.MathEx.loadImageFromJar;

/**
 *
 * @author &{user}
 */
public class ZombieDefenseOverlay extends Overlay {

    private Player player;	    //to get player stats
    private ZombieManager zombies;  //to get stats about number of zombies remaining, etc.
    private JButton buyButton;
    private JButton quitButton;
    private JButton optionsButton;  //where gore can be censored!
    private JLabel ammolabel;
    private JLabel guniconlabel;
    private JLabel fpslabel;
    private JLabel zombielabel;
    private JLabel wavelabel;
    private JLabel gunnamelabel;
    private JLabel cashlabel;
    private JLabel wavetimelabel;
    private static FadingTextOutput textOutput;
    //buy menu components
    private JPanel buyMenuBG;
    private JButton backButton;
    private boolean menuUp = false;
    private static Rectangle healthBar;
    private double fps;
    private static ImageIcon[] gunicons = {
        getGunIcon("pistolicon.png"),
        getGunIcon("mp5icon.png"),
        getGunIcon("shotgunicon.png"),
        getGunIcon("ak47icon.png"),
        getGunIcon("m249icon.png"),
        getGunIcon("chaingunicon.png")
    };

    public ZombieDefenseOverlay(JPanel panel, Player player, ZombieManager zombies) {
        super(panel);
        this.player = player;
        this.zombies = zombies;
        healthBar = new Rectangle(gamePanel.getWidth() / 2, gamePanel.getHeight() - 10, gamePanel.getWidth() / 2, 10);

        //set layout of main panel
        SpringLayout layout = new SpringLayout();
        gamePanel.setLayout(layout);

        //create text output
        getMainTextOutput();

        //create labels and gun icon
        ammolabel = createLabel();
        guniconlabel = createLabel();
        fpslabel = createLabel();
        zombielabel = createLabel();
        wavelabel = createLabel();
        gunnamelabel = createLabel();
        cashlabel = createLabel();
	wavetimelabel = createLabel();

        //use layout to arrange

        //fix ammolabel
        layout.putConstraint(SpringLayout.SOUTH, ammolabel, panel.getHeight() - healthBar.y - 25, SpringLayout.SOUTH, gamePanel);
        layout.putConstraint(SpringLayout.EAST, ammolabel, -5, SpringLayout.EAST, gamePanel);

        //fix gun icon
        layout.putConstraint(SpringLayout.SOUTH, guniconlabel, panel.getHeight() - healthBar.y - 25, SpringLayout.SOUTH, gamePanel);
        layout.putConstraint(SpringLayout.EAST, guniconlabel, -10, SpringLayout.WEST, gunnamelabel);

        //fix gun name
        layout.putConstraint(SpringLayout.SOUTH, gunnamelabel, 5, SpringLayout.NORTH, ammolabel);
        layout.putConstraint(SpringLayout.EAST, gunnamelabel, -5, SpringLayout.EAST, gamePanel);

        //fix fps label
        layout.putConstraint(SpringLayout.NORTH, fpslabel, 5, SpringLayout.NORTH, gamePanel);
        layout.putConstraint(SpringLayout.WEST, fpslabel, 5, SpringLayout.WEST, gamePanel);

        //fix zombie label
        layout.putConstraint(SpringLayout.WEST, zombielabel, 5, SpringLayout.WEST, gamePanel);
        layout.putConstraint(SpringLayout.SOUTH, zombielabel, -5, SpringLayout.SOUTH, gamePanel);

        //fix wave label
        layout.putConstraint(SpringLayout.WEST, wavelabel, 5, SpringLayout.WEST, gamePanel);
        layout.putConstraint(SpringLayout.SOUTH, wavelabel, -20, SpringLayout.SOUTH, gamePanel);
        
        //fix cash label
        layout.putConstraint(SpringLayout.SOUTH,cashlabel,-15,SpringLayout.NORTH,gunnamelabel);
        layout.putConstraint(SpringLayout.EAST,cashlabel,-5,SpringLayout.EAST,gamePanel);
	
	//fix wave time label
        layout.putConstraint(SpringLayout.WEST, wavetimelabel, 5, SpringLayout.WEST, gamePanel);
        layout.putConstraint(SpringLayout.SOUTH, wavetimelabel, -35, SpringLayout.SOUTH, gamePanel);

        //add buttons to the panel
        buyButton = createButton("buyicon.png");
        quitButton = createButton("surrendericon.png");
        optionsButton = createButton("optionsicon.png");

        //make sure the button panel always stays in the upper right corner
        layout.putConstraint(SpringLayout.NORTH, quitButton, 5, SpringLayout.NORTH, gamePanel);
        layout.putConstraint(SpringLayout.NORTH, optionsButton, 5, SpringLayout.NORTH, gamePanel);
        layout.putConstraint(SpringLayout.NORTH, buyButton, 5, SpringLayout.NORTH, gamePanel);
        layout.putConstraint(SpringLayout.EAST, quitButton, -10, SpringLayout.EAST, gamePanel);
        layout.putConstraint(SpringLayout.EAST, optionsButton, -10, SpringLayout.WEST, quitButton);
        layout.putConstraint(SpringLayout.EAST, buyButton, -10, SpringLayout.WEST, optionsButton);

        //end of in-game ui setup

        //buy menu

        //background
        buyMenuBG = new JPanel();
        buyMenuBG.setOpaque(true);
        buyMenuBG.setBackground(new Color(0, 0, 0, .3f)); //gray semi-transparent background
        buyMenuBG.setPreferredSize(gamePanel.getSize());
        buyMenuBG.setLocation(0, 0);
        buyMenuBG.setVisible(false); //do not show yet
        SpringLayout slayout = new SpringLayout();
        buyMenuBG.setLayout(slayout);

        gamePanel.add(buyMenuBG);

        //main panel
        JPanel mainPanel = new JPanel();
        mainPanel.setOpaque(false);
        buyMenuBG.add(mainPanel);

        GridLayout glayout = new GridLayout(6,0);    //six columns for 6 guns and 6 items
        
        mainPanel.setLayout(glayout);
        
        Dimension panelDims = new Dimension(gamePanel.getWidth() * 3 / 8, gamePanel.getHeight() * 3 / 4);
        mainPanel.setPreferredSize(panelDims);
        mainPanel.setMinimumSize(panelDims);
        mainPanel.setMaximumSize(panelDims);
        
        slayout.putConstraint(SpringLayout.NORTH, mainPanel, gamePanel.getHeight() / 8, SpringLayout.NORTH, buyMenuBG);
        slayout.putConstraint(SpringLayout.WEST, mainPanel, gamePanel.getWidth() / 8, SpringLayout.WEST, buyMenuBG);

        //add gun buying boxes to main panel
        mainPanel.setLayout(glayout);
        mainPanel.add(createGunBox("pistolBuyIcon.png", Gun.pistol));
        mainPanel.add(createGunBox("mp5BuyIcon.png", Gun.smg));
        mainPanel.add(createGunBox("shotgunBuyIcon.png", Gun.shotgun));
        mainPanel.add(createGunBox("ak47BuyIcon.png",Gun.assaultRifle));
        mainPanel.add(createGunBox("m249BuyIcon.png",Gun.lmg));
        mainPanel.add(createGunBox("chaingunBuyIcon.png",Gun.chaingun));
        

        //create back button
        backButton = createButton("resumeicon.png");
        backButton.setFocusable(false);
        backButton.addActionListener(this);
        buyMenuBG.add(backButton);
        
        slayout.putConstraint(SpringLayout.SOUTH,backButton,-100,SpringLayout.SOUTH,buyMenuBG);
        slayout.putConstraint(SpringLayout.EAST,backButton,-5,SpringLayout.EAST,buyMenuBG);
    }

    private JPanel createGunBox(String iconName, Gun gun) {

        JPanel box = new JPanel();
        box.setOpaque(true);
        box.setBackground(new Color(1f,0f,0f,.4f));
        box.setBorder(BorderFactory.createBevelBorder(0));
        SpringLayout layout = new SpringLayout();
        box.setLayout(layout);

        //create item icon
        JLabel icon = new JLabel();
        icon.setForeground(Color.gray);
        icon.setToolTipText(gun.getName());
        icon.setIcon(new ImageIcon(getIcon(iconName)));

        //create buttons
        JButton buyButton = new JButton("Buy Gun");
        buyButton.setForeground(Color.black);
        buyButton.setBackground(new Color(1f,0f,0f,.8f));
        buyButton.setBorder(BorderFactory.createRaisedBevelBorder());
        buyButton.setFocusable(false);
        buyButton.setToolTipText("$" + gun.getGunCost());

        JButton buyAmmoButton = new JButton("Buy Ammo");
        buyAmmoButton.setForeground(Color.black);
        buyAmmoButton.setBackground(new Color(1f,.0f,.0f,.8f));
        buyAmmoButton.setBorder(BorderFactory.createRaisedBevelBorder());
        buyAmmoButton.setFocusable(false);
        buyAmmoButton.setToolTipText("$" + gun.getAmmoCost());
        
        //enable/disable
        if(gun.isLocked()){
            buyButton.setEnabled(true);
            buyAmmoButton.setEnabled(false);
        }else{
            buyButton.setEnabled(false);
            buyAmmoButton.setEnabled(true);
        }

        //listen for buttons pressed
        GunBuyListener listener = new GunBuyListener(gun, buyButton, buyAmmoButton);

        buyButton.addActionListener(listener);
        buyAmmoButton.addActionListener(listener);

        //use springlayout to fix positions
        //icon
        layout.putConstraint(SpringLayout.WEST, icon, 0, SpringLayout.WEST, box);
        layout.putConstraint(SpringLayout.NORTH, icon, 0, SpringLayout.NORTH, box);

        //buy button
        layout.putConstraint(SpringLayout.WEST, buyButton, 10, SpringLayout.EAST, icon);
        layout.putConstraint(SpringLayout.NORTH, buyButton, 5, SpringLayout.NORTH, box);

        //buy ammo button
        layout.putConstraint(SpringLayout.WEST, buyAmmoButton, 10, SpringLayout.EAST, buyButton);
        layout.putConstraint(SpringLayout.NORTH, buyAmmoButton, 5, SpringLayout.NORTH, box);

        //add to JPanel
        box.add(icon);
        box.add(buyButton);
        box.add(buyAmmoButton);
        
        //done
        return box;
    }

    private JLabel createLabel() {
        JLabel label = new JLabel();
        gamePanel.add(label);
        label.setForeground(Color.white);
        label.setBackground(Color.black);
        label.setIgnoreRepaint(true);
        label.setOpaque(false);
        return label;
    }

    private JButton createButton(String iconImage) {
        JButton b = new JButton();
        b.addActionListener(this);
        b.setIgnoreRepaint(true);
        b.setFocusable(false);
        b.setOpaque(false);
        b.setBorder(null);

        if (iconImage != null) {
            b.setContentAreaFilled(false);
            setButtonIcons(b, iconImage);
        }

        gamePanel.add(b);
        return b;
    }

    /**
     * Draw the overlay, with fps readout.
     * @param g
     * @param fps 
     */
    public void draw(Graphics2D g) {
        //draw player health
        g.setColor(Color.red);
        g.fillRect(healthBar.x, healthBar.y, healthBar.width, healthBar.height);
        g.setColor(Color.green);
        g.fillRect(healthBar.x, healthBar.y, (int) (healthBar.width * player.getHealthRatio()), healthBar.height);

        //draw text
        textOutput.draw(g);
    }

    public void update(long elapsedTime) {
        //update gun stats
        Gun gun = player.getGun();
        gunnamelabel.setText(gun.getName());
        ammolabel.setText(gun.getLoadedAmmo() + "/" + gun.getStowedAmmo());

        //update zombie stats
        wavelabel.setText("Wave: " + zombies.getCurrentWave());
	
	if(!zombies.isWaiting()){
	    zombielabel.setText("Zombies Remaining: " + (zombies.getTotalForWave() - player.getKillCountCurrentWave()));
	}else{
	    zombielabel.setText("");
	}

        //draw gun icon - above ammo stats
        guniconlabel.setIcon(gunicons[player.getGun().ordinal()]);

        //update fps
        fpslabel.setText("fps: " + fps);
        
        //update cash
        cashlabel.setText("$" + player.getCash());
	
	//update wave time
	if(zombies.isWaiting()){
	    wavetimelabel.setText("Time to next wave: " + zombies.getTimeUntilNextWave()/1000);
	}else{
	    wavetimelabel.setText("");
	}

        //update text
        textOutput.update(elapsedTime);
    }

    public void actionPerformed(ActionEvent e) {
        //buy button pressed
        if (e.getSource() == buyButton) {
            //pause game
            menuUp = true;

            //show buy menu
            buyMenuBG.setVisible(true);

            //hide other buttons
            buyButton.setVisible(false);
            optionsButton.setVisible(false);
            quitButton.setVisible(false);
            
            //hide gun icon
            guniconlabel.setVisible(false);
           

        }else if(e.getSource() == quitButton){
            //stop the game
            System.exit(0);
        } else if (e.getSource() == backButton) {
            //unpause game
            menuUp = false;

            //hide menu
            buyMenuBG.setVisible(false);

            //show other buttons
            buyButton.setVisible(true);
            optionsButton.setVisible(true);
            quitButton.setVisible(true);
            
            //and gun icon
            guniconlabel.setVisible(true);
        }
    }

    /**
     * Returns whether or not the user
     * is currently playing the game, or
     * for example, is looking at a full-
     * screen menu.
     * @return 
     */
    public boolean isUserPlaying() {
        return menuUp;
    }

    public void setFps(double fps) {
        this.fps = fps;
    }

    /**
     * Outputs a message to the text output.
     * @param text 
     */
    public void message(String text) {
        textOutput.print(text);
    }

    private static ImageIcon getGunIcon(String name) {
        Image orig = getIcon(name);
        BufferedImage icon = new BufferedImage(orig.getWidth(null), orig.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = icon.createGraphics();
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .8f));
        g.drawImage(orig, 0, 0, null);
        g.dispose();

        return new ImageIcon(icon);
    }

    private static void setButtonIcons(JButton button, String iconname) {

        Image orig = getIcon(iconname);

        //create transparent icon
        BufferedImage icon = new BufferedImage(orig.getWidth(null), orig.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = icon.createGraphics();
        g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .75f));
        g.drawImage(orig, 0, 0, null);
        g.dispose();

        //set icon
        button.setIcon(new ImageIcon(icon));

        //create mouseover icon
        BufferedImage mouseicon = new BufferedImage(orig.getWidth(null), orig.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        g = mouseicon.createGraphics();
        g.drawImage(orig, 0, 0, null);
        g.setColor(Color.red);
        g.drawOval(5, 5, orig.getWidth(null) - 10, orig.getHeight(null) - 10);
        g.dispose();

        //set mouseover icon
        button.setRolloverIcon(new ImageIcon(mouseicon));

        //create pressed icon
        BufferedImage pressedicon = new BufferedImage(orig.getWidth(null) + 5, orig.getHeight(null) + 5, BufferedImage.TYPE_INT_ARGB);
        g = pressedicon.createGraphics();
        g.drawImage(mouseicon, 5, 5, null);
        g.dispose();

        //set pressed icon
        button.setPressedIcon(new ImageIcon(pressedicon));
    }

    private static Image getIcon(String name) {
        return loadImageFromJar("/icons/" + name);
    }

    private class GunBuyListener implements ActionListener {

        JButton b1, b2;
        Gun gun;

        /**
         * Creates a listener for a gun buying box.
         * @param gunNumber
         * @param buyGun
         * @param buyAmmo 
         */
        public GunBuyListener(Gun gun, JButton buyGun, JButton buyAmmo) {
            b1 = buyGun;
            b2 = buyAmmo;
            this.gun = gun;
        }

        /*
         * Modify player object based on action performed.
         */
        public void actionPerformed(ActionEvent ae) {
            if (ae.getSource() == b1) {
                //pressed buy gun button
                
                //check if player has enough money
                if(player.getCash() >= gun.getGunCost()){
                    //unlock the gun
                    gun.setLocked(false);
                
                    //switch player to new gun
                    player.setGun(gun);
                    
                    //player pays for it
                    player.takeCash(gun.getGunCost());
                    
                    //print message
                    textOutput.print("Got a new gun: " + gun.getName());
                    
                    //update cash label - to show feedback
                    cashlabel.setText("$" + player.getCash());
                    
                    //deactivate this button
                    b1.setEnabled(false);
                    
                    //enable buying amm
                    b2.setEnabled(true);
                }else{
                    //give some signal that there isn't enough money
                    textOutput.print("Not enough cash to buy " + gun.getName());
                }
                
            } else if (ae.getSource() == b2) {
                //pressed buy ammo button
                
                //check if player has enough money
                if(player.getCash() >= gun.getAmmoCost()){
                    //refill ammo
                    gun.refill();
                    
                    //player pays
                    player.takeCash(gun.getAmmoCost());
                    
                    //update cash label - to show feedback
                    cashlabel.setText("$" + player.getCash());
                    
                    //print message
                    textOutput.print("Bought some " + gun.getName() + " ammo");
                 
                }else{
                    //give some signal that there isn't enough money
                    textOutput.print("Not enough cash to buy " + gun.getName() + " ammo");
                }
            }
        }
    }
    
    //create and get the text output box
    public static TextOutput getMainTextOutput(){
        if(textOutput == null){
            textOutput = new FadingTextOutput(5, 25, new Font("Arial", Font.PLAIN, 12), 12, 8, 10000, 5000);
            textOutput.print("Hi, this game");
            textOutput.print("was programmed by");
            textOutput.print("Connor Willison");
        }
        
        return textOutput;
    }
}
